﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Cyss.Core.Api.Models;
using System;
using Cyss.Core;
using Microsoft.AspNetCore.Mvc;

namespace Cyss.Core.Api
{

    /// <summary>
    /// 验证Api key
    /// </summary>
    public class ApiKeyFiter : Attribute, IActionFilter
    {

        private readonly ApiKeyConfig _apiKeyConfig;
        public ApiKeyFiter(ApiKeyConfig apiKeyConfig)
        {
            _apiKeyConfig = apiKeyConfig;
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {

        }


        public void OnActionExecuting(ActionExecutingContext context)
        {

            if (!_apiKeyConfig.IsEnabled)
            {
                return;
            }

            OperateResult OperateResult = new OperateResult();
            //获取token
            var keyobj = context.HttpContext.Request.Headers["ApiKey"];

            if (keyobj.Count<=0)
            {
                OperateResult.CodeType =OperateResultCodeType.ApiKey;
                OperateResult.Message = "ApiKey不能为空";
                context.Result = new JsonResult(OperateResult);
                return;
            }
            string key = keyobj[0];

            if (string.IsNullOrWhiteSpace(key))
            {
                OperateResult.CodeType =OperateResultCodeType.ApiKey;
                OperateResult.Message = "ApiKey不能为空";
                context.Result = new JsonResult(OperateResult);
                return;
            }

            KeyVerification keyVerification = new KeyVerification(key, _apiKeyConfig);
            if (!keyVerification.IsSuccess)
            {
                OperateResult.CodeType =OperateResultCodeType.ApiKey;
                OperateResult.Message = "ApiKey验证失败！";
                context.Result = new JsonResult(OperateResult);
                return;
            }
        }


    }

    /// <summary>
    /// key验证类
    /// </summary>
    public class KeyVerification
    {
        /// <summary>
        /// 加密过的key
        /// </summary>
        private string _keyInput { set; get; }

        /// <summary>
        /// 解密后的key
        /// </summary>
        private string _keyInputDecrypt { set; get; }

        /// <summary>
        /// key中带的时间
        /// </summary>
        private long _toFileTimeUtc { set; get; }

        /// <summary>
        /// 原始key
        /// </summary>
        private string _key { set; get; }

        /// <summary>
        ///设置的 key 用于和传入的key 匹配
        /// </summary>
        private ApiKeyConfig _apiKeyConfig { set; get; }


        /// <summary>
        /// key验证类
        /// </summary>
        /// <param name="inputKey">用户传入的key</param>
        /// <param name="apiKey">系统设置的key</param>
        public KeyVerification(string inputKey, ApiKeyConfig apiKeyConfig)
        {
            _keyInput = inputKey;
            _apiKeyConfig = apiKeyConfig;

            KeyDecrypt();

            this._toFileTimeUtc = ToFileTimeUtc();
            this._key = AnalysisKey();
        }

        /// <summary>
        /// 解密key
        /// </summary>
        private void KeyDecrypt()
        {
            _keyInputDecrypt = EncryptHelper.AESDecrypt(_keyInput, _apiKeyConfig.EncryptedKey);

        }

        /// <summary>
        /// 获取key里面的时间戳
        /// </summary>
        /// <returns></returns>
        private long ToFileTimeUtc()
        {
            string positions = _keyInputDecrypt.Substring(0, _keyInputDecrypt.IndexOf("-"));
            string strHead = _keyInputDecrypt.Substring(0, _keyInputDecrypt.IndexOf("-") + 1);

            int[] positionIndex = Array.ConvertAll<string, int>(positions.Split("*"), s => int.Parse(s));
            string ToFileTimeUtc = _keyInputDecrypt.Replace(strHead, "").Substring(positionIndex[0], positionIndex[1]);
            return long.Parse(ToFileTimeUtc);
        }

        private string AnalysisKey()
        {
            string positions = _keyInputDecrypt.Substring(0, _keyInputDecrypt.IndexOf("-") + 1);
            return _keyInputDecrypt.Replace(positions, "").Replace(this._toFileTimeUtc.ToString(), "");

        }

        /// <summary>
        /// 是否验证成功
        /// </summary>
        public bool IsSuccess
        {
            get
            {
                return _key == _apiKeyConfig.ApiKey;

            }
        }

    }
}
